package org.vdab.projects.tasks.client.dal;

import java.util.List;

import org.vdab.projects.tasks.client.TasksService;
import org.vdab.projects.tasks.client.TasksServiceAsync;
import org.vdab.projects.tasks.client.entities.ClientTaskBook;
import org.vdab.projects.tasks.client.entities.ClientTaskList;
import org.vdab.projects.tasks.client.util.DelayedList;
import org.vdab.projects.tasks.client.util.ICommand;
import org.vdab.projects.tasks.client.util.MessageGuard;
import org.vdab.projects.tasks.shared.entities.ITaskBook;
import org.vdab.projects.tasks.shared.entities.ITaskList;
import org.vdab.projects.tasks.shared.entities.impl.Task;
import org.vdab.projects.tasks.shared.entities.impl.TaskBook;
import org.vdab.projects.tasks.shared.entities.impl.TaskList;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

/***
 *   The GWTEntityManager is the manager for the ClientEntities. This is
 *   the only one class responsible for creation of ClientEntities.
 * 
 *   The GWTEntityManager is also the single user of the Task Service
 * 
 *   For now, the GWTEntityManager is implemented as a singleton, but this
 *   may be changed in the future. Therefore a ClientEntity hold a
 *   reference to it's own manager object.
 *         
 * @author stijn
 * 
 *       
 * 
 */
public class GWTEntityManager {

	private static GWTEntityManager instance = new GWTEntityManager();

	public static GWTEntityManager get() {
		return instance;
	}

	private static final TasksServiceAsync tasksService = GWT
			.create(TasksService.class);

	public void getTaskBooks(final DelayedList<ClientTaskBook> into) {
		MessageGuard
				.Log("in GWTEntityManager calling taskService.getTaskBook()");
		final GWTEntityManager finalThis = this;

		tasksService.getTaskBook(new AsyncCallback<List<TaskBook>>() {
			@Override
			public void onSuccess(List<TaskBook> result) {
				MessageGuard.Log("in onSuccess of getTaskBook()");
				MessageGuard.Log("retrieved " + result.size() + " taskBook(s)");
				for (TaskBook tb : result) {
					ClientTaskBook ctb = new ClientTaskBook(tb, finalThis);
					try {
						into.addEntity(ctb);
					} catch (Exception e) {
						MessageGuard.Log(e.getLocalizedMessage());
					}
				}
			}

			@Override
			public void onFailure(Throwable caught) {
				MessageGuard.Log(caught.getLocalizedMessage());
			}
		});
	}

	public void loadTaskListByKey(String key, AsyncCallback<TaskList> onLoaded) {
		MessageGuard
				.Log("in GWTEntityManager calling taskService.getTaskListByKey()");
		tasksService.getTaskListByKey(key, onLoaded);
	}

	public void saveTaskBook(ITaskBook taskBook) throws Exception {
		taskBook.execute(new ICommand<TaskBook>() {			
			@Override
			public void execute(TaskBook entity) throws Exception {
				MessageGuard.Log("in GWTEntityManager calling tasksService.saveTaskBook()");
				if(entity==null){
					MessageGuard.Log("Taskbook==NULL");
				}
				tasksService.saveTaskBook(entity,new AsyncCallback<Void>() {
					@Override
					public void onSuccess(Void result) {
						MessageGuard.Log("TaskBook Saved !");
					}

					@Override
					public void onFailure(Throwable caught) {
						MessageGuard.Log("Error(saveTaskBook): "
								+ caught.getLocalizedMessage());
					}
				});
			}
		});

	}

	public void saveTaskList(ITaskList taskList) throws Exception {
		taskList.execute(new ICommand<TaskList>() {
			@Override
			public void execute(TaskList entity) throws Exception {
				MessageGuard.Log("in GWTEntityManager calling tasksService.saveTaskList()");
				tasksService.saveTaskList(entity, new AsyncCallback<Void>() {

					@Override
					public void onSuccess(Void result) {
						Window.alert("TaskList Saved !");
					}

					@Override
					public void onFailure(Throwable caught) {
						Window.alert("Error(saveTaskList): "
								+ caught.getLocalizedMessage());
					}
				});

			}
		});
	}

	public void saveTask(Task task) {
		MessageGuard.Log("in GWTEntityManager calling tasksService.saveTask()");
		tasksService.saveTask(task, new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void result) {
				Window.alert("Task Saved !");
			}

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Error(saveTask): " + caught.getLocalizedMessage());
			}
		});
	}

	public ClientTaskBook createNewTaskBook() throws Exception {
		MessageGuard.Log("in GWTEntityManager createNewTaskBook()");
		TaskBook taskBook = new TaskBook().init();
		saveTaskBook(taskBook);
		return new ClientTaskBook(taskBook, this);
	}

	public ClientTaskList createTaskList(String key) {
		MessageGuard.Log("in GWTEntityManager createTaskList() key:" + key);
		// Create only a ClientTaskBook, it will load itself when needed
		return new ClientTaskList(key, this);
	}
}
